/**
 * javascript 模板引擎
 * Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
 * @version 1.0
 * @author yangjian102621@gmail.com
 */
var JTemplate = function() {

    if ( String.inc == undefined ) {String.prototype.inc=function(s){return this.indexOf(s)>-1?true:false}};
    if ( String.trim == undefined ) {String.prototype.trim = function() {return this.replace(/^\s+|\s+$/g, '');}}

    var o = {};
    o.GDATA = {};		//全局数据变量
    o.tagPrefix = "{["; //标签前缀
    o.tagSuffix = "]}"; //标签后缀
    o.debug = false; //是否开启调试模式
    o.__HELPER__ = {};  //自定标签解析函数库

    //清除导入的全局数据
    o.clear = function() {
        this.GDATA = {};
        return this;
    }

    //更改配置参数
    o.config = function(name, value) {
        this[name] = value;
    }

    //注册变量
    o.assign = function(key, value) {
        this.GDATA[key] = value;
        return this;
    }

    //添加自定义标签解析库
    o.helper = function(tagName, callback) {
        if ( typeof this.__HELPER__[tagName] != "function" ) {
            this.__HELPER__[tagName] = callback;
        }
    }

    /**
     * 渲染模板
     * @param tpl 模板内容或者模板id
     * @param data
     */
    o.render = function(tpl, data) {

        if ( document.getElementById(tpl) ) {		//如果传入的是id, 则获取内容
            tpl = document.getElementById(tpl).innerHTML;
        }

        var __GDATA__ = this.merge(this.GDATA, data);
        var __CODE__ = "";		//待执行的js代码

        append("var r = [];", true);

        //标签匹配正则
        var __suffix = '', __prefix = '';   //标签前后缀转换为正则
        for ( var i = 0; i < this.tagSuffix.length; i++ ) __suffix += "\\"+this.tagSuffix[i];
        for ( var i = 0; i < this.tagPrefix.length; i++ ) __prefix += "\\"+this.tagPrefix[i];
        //build the tag regExp
        try {
            var reg = eval("/"+__prefix+"([^"+__suffix+"]+)"+__suffix+"/g");
        } catch (e) {console.log(e); throw e;}

        if ( this.debug ) console.log(reg);

        var cursor = 0;  //当前查找游标的位置
        var match;	//当前匹配到的对象
        while ( match = reg.exec(tpl) ) {
            //添加非逻辑代码
            append(tpl.slice(cursor, match.index));
            cursor = match.index + match[0].length;
            var helper; //自定义标签解析器

            //匹配双标签的结束标签，如 if 标签和 loop 标签
            if ( match[0] == this.tagPrefix+"/if"+this.tagSuffix
                || match[0] == this.tagPrefix+"/loop"+this.tagSuffix ) {
                __CODE__ += "}\n";
                continue;
            }

            //判断不同的标签，执行不同的编译规则
            if ( match[0].inc(this.tagPrefix+"loop") ) {
                //编译循环
                compileLoop(match[1]);

            } else if ( match[0].inc(this.tagPrefix+"if") ) {
                //编译条件标签
                complieIf(match[1]);

            } else if ( match[0].inc(this.tagPrefix+"expr:") ) {
                //编译自定义表达式
                compileExpr(match[1]);

            } else if ( match[0].inc(this.tagPrefix+"wxtime:") ) {
                //编译时间标签
                append(compileTimeString(match[1]));

            } else if ( helper = getCustomTagHelper(match[0]) ) {
                //编译自定标签
                compileCustomTag(helper, match);

            } else {
                //编译变量
                compileVar(match[1]);
            }

        }

        append(tpl.substring(cursor));
        __CODE__ += 'return r.join("");';
        if ( this.debug ) {
            console.log(__CODE__);
        }
		var html = '';
		try {
			html =  new Function(__CODE__).apply(__GDATA__);
		
		} catch (e) {
			console.log(e);
		} 
		return html;

        /**
         * 追加代码到函数字符串
         * @param line 代码
         * @param native 是否js原生代码，如果是原生js代码就直接输出
         */
        function append(line, native) {

            if ( !line ) return;
            if ( native ) {
                __CODE__ += line+"\n";
            } else {
                var code = line.replace(/'/g, "\\\'").replace(/[\n\t\r]+/g, " ");
                __CODE__ += "r.push('"+code+"');\n";
            }
            return this;
        }

        //编译变量标签
        function compileVar(match) {

            if ( __GDATA__[match] != undefined ) {
                //1. 全局变量
                append("r.push(this."+match+")", true);
            } else {
                //2. 局部变量
                append("r.push("+match+")", true);
            }

        }

        //编译循环标签（loop标签） {{loop list value index}}
        function compileLoop(match) {

            var params = match.replace(/\s+/, " ").split(" ");
            //console.log(params);
            append("for ( var i = 0; i < this."+params[1]+".length; i++ ) {", true);
            //标签中新定义的变量初始化
            append("var "+params[2].replace(this.tagSuffix, '').replace(/\s+/g, '')+" = this."+params[1]+"[i];", true);
            if ( params[3] ) {
                append("var "+params[3].replace(this.tagSuffix, '').replace(/\s+/g, '')+" = i;", true);
            }

        }

        //编译条件标签（if标签）
        function  complieIf(match) {
            //获取判断条件 if value == 'xiaoming'
            match = match.replace("if", "").trim();
            //console.log(match);
            append("if ( "+match+" ) {", true);
        }

        //编译expr表达式标签
        function compileExpr(match) {
            match = match.replace("expr:", "").trim();
            append(match, true);

        }

        //编译时间标签
        function compileTimeString(match) {

            var ctime = new Date();
            var otime = match.replace("wxtime:", "");

            var d = new Date();
            d.setTime(otime*1000);
            if ( otime*1000 > ctime.getTime() ) {
                return d.getFullYear()+'年'+(d.getMonth()+1)+'月'+d.getDate()+'日';
            }

            var t = Math.ceil((ctime.getTime()/1000)) - otime;
            if ( t < 10 )        return '刚刚';                            //just now
            if ( t < 60 )        return t+'秒前';                        //under one minuts
            if ( t < 3600 )        return Math.floor(t/60)+'分钟前';        //under one hour
            if ( t < 86400 && d.getDate() == new Date().getDate() ) return Math.floor(t/3600)+'小时前';        //under one day
            if ( t < 86400 && d.getDate() < new  Date().getDate() ) return "昨天";    //yesterday
            if ( t < 864000 )    return Math.floor(t/86400)+'天前';        //under 10 days

            if ( t < 31104000 && d.getFullYear() == new Date().getFullYear() ) { //under one year
                return (d.getMonth()+1)+'月'+d.getDate()+'日';
            }

            return d.getFullYear()+'年'+(d.getMonth()+1)+'月'+d.getDate()+'日';

        }

        //解析自定义标签
        function compileCustomTag(helper, match) {

            //获取参数
            var reg = /^\w+:\s+([^\|]+)\s+\|\s+(.*?)$/;
            var m = reg.exec(match[1]);
            var html;
            //console.log(m);
            if ( m ) {
                if ( m[1].indexOf("$") == 0 ) { //参数是变量
                    html = helper(__GDATA__[m[1].substr(1)], m[2].replace(/['"]/g, ''));
                } else {
                    html = helper(m[1], m[2].replace(/['"]/g, '')); //参数本身就是字符串
                }
                append(html);
            }
        }

        //获取自定义标签的解析器
        function getCustomTagHelper(match) {

            if ( o.__HELPER__.length == 0 ) return false;

            for ( var name in o.__HELPER__ ) {
                if ( match.indexOf(o.tagPrefix+name+":") == 0 ) {
                    return o.__HELPER__[name];
                }
            }

            return false;
        }


    }

    //合并两个对象
    o.merge = function(o1, o2) {

        for ( var key in o2 ) {
            o1[key] = o2[key];
        }
        return o1;

    }

    return o;

}();
